package model;

import java.awt.geom.Point2D;
import java.util.Collection;

import model.commands.AbstractModelCommand;
import ctf.model.Side;
import ctf.network.ProtocolError;


/**	Interface for the model which defines all necessary functionality to interact with the Simulator.
 * @author N. Bhatia, A. Butt, N. Evans, C. Levesque, P. OKeefe
 *
 */
public interface IModel extends IPublishable {
	/**	This function is called on the model to update the data contained in the model after a period of time has elapsed.
	 * @param elapsedTimeInMillis - time that has passed in milliseconds since the last update was called.
	 * @return true if simulation should continue running, false if it should pause
	 * @throws ProtocolError 
	 */
	public boolean update(int elapsedTimeInMillis);
	
	/**	Adds a command to the model's command queue to be executed in the first update request
	 * when elapsed time >= the command's execution time.
	 * @param elapsedTimeInMillis - time that has passed in milliseconds since the last update was called.
	 * @throws ProtocolError 
	 */
	public void addCommand(AbstractModelCommand command) throws ProtocolError;

	public void setFlagPosition(Side side, Point2D point) throws ProtocolError;

	/**	Function used to get all the trees in Point2D format
	 * @return	- A collection of trees in Point2D
	 */
	public Collection<Point2D> trees();

	/**	Places the player on a side at a specific point based on his player number.
	 * @param side	- Side the player is on
	 * @param playerNum - The number of the player
	 * @param position - The position the player wants to be placed at.
	 */
	public void placePlayer(Side side, int playerNum, Point2D position);

	/**	Sets the game time in milliseconds
	 * @param newTimeInMs - the game time in milliseconds
	 */
	public void setTime(int newTimeInMs);
	/**	Returns the game time in ms
	 */
	public int getTime();

	/** Attaches an angular velocity to a certain player on a side.
	 * @param side - side the player is on
	 * @param playerNum - the players number
	 * @param newAngularVelocity - the desired angular velocity that the player wants to reach.
	 */
	public void spinPlayer(Side side, int playerNum, float newAngularVelocity);

	/**	Attaches a desired acceleration to a certain player on a side.
	 * @param side - Side the player is on
	 * @param playerNum - the number of the player
	 * @param newAcceleration - the desired acceleration of the player.
	 * @throws ProtocolError 
	 */
	public void acceleratePlayer(Side side, int playerNum, float newAcceleration);
	
	/**
	 * Resets the model
	 */
	public void reset();

	/**
	 * Ensures a requested player is valid on that side.
	 * @param side The side to check
	 * @param playerNum The player number to check
	 * @return True if player exists
	 */
	public boolean playerExists(Side side, int playerNum);

}
